﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Configuration;
using System.Data;
using System.Windows;
using Bainx.Extend;
using Bainx.Data;

namespace Bainx
{
    public class User
    {
        #region //私有成员

        private XmlHelper service = new XmlHelper();

        private SQLite DB;

        #endregion

        #region //成员属性
        private int uid;
        /// <summary>
        /// 获取用户数据ID标识
        /// </summary>
        public int Uid
        {
            get { return uid; }
        }

        private string name;
        /// <summary>
        /// 获取用户名
        /// </summary>
        public string Name
        {
            get { return name; }
        }
        private string nickname;
        /// <summary>
        /// 获取或设置昵称
        /// </summary>
        public string Nickname
        {
            get { return nickname; }
            set { nickname = value; }
        }
        private string password;
        /// <summary>
        /// 获取或设置密码,获取的是一个经过MD5加密后的字符串
        /// </summary>
        public string Password
        {
            get { return password; }
            set 
            { 
                password = value;
                if (remember)
                {
                    saveUserInfoToLocalDatabase();
                }
            }
        }
        private bool remember;
        /// <summary>
        /// 获取或设置记住密码,数据保存本地
        /// </summary>
        public bool Remember
        {
            get { return remember; }
            set 
            {
                if (uid > 0 && name.Equals(""))
                {
                    remember = value;
                    saveUserInfoToLocalDatabase();
                }
            }
        }
        private bool autoLogin;
        /// <summary>
        /// 获取或设置自动登录,数据保存本地
        /// </summary>
        public bool AutoLogin
        {
            get { return autoLogin; }
            set 
            {
                if (uid > 0 && name.Equals(""))
                {
                    autoLogin = value; 
                    saveUserInfoToLocalDatabase();
                }                
            }
        }
        private int loginCount;
        /// <summary>
        /// 获取登录次数,数据保存到服务器
        /// </summary>
        public int LoginCount
        {
            get { return loginCount; }
        }
        private DateTime lastLogDataTime;
        /// <summary>
        /// 获取上一次登录时间,数据保存到服务器
        /// </summary>
        public DateTime LastLogDataTime
        {
            get { return lastLogDataTime; }
        }
        private string background;
        /// <summary>
        /// 获取或设置用户背景图片设置,数据保存到本地
        /// </summary>
        public string Background
        {
            get { return background; }
            set { background = value; }
        }
        private Exception exception;
        /// <summary>
        /// 获取当前错误信息
        /// </summary>
        public Exception Exception
        {
            get { return exception; }
            protected set 
            {
                exception = value;
                if (OnException != null) OnException(new ExceptionEventArgs(value));
            }
        }
        
        private EnumState state;
        /// <summary>
        /// 用户状态,数据保存到服务器
        /// </summary>
        public EnumState State
        {
            get { return state; }
            set 
            {
                try
                {
                    state = value;
                    if (OnStateChanged != null) OnStateChanged(this, new EventArgs());
                }
                catch (Exception ex)
                {
                    Exception = new Exception("用户状态改变时异常", ex);
                }
            }
        }


        #endregion

        #region //事件
        /// <summary>
        /// 事件：当用户登录时发生
        /// </summary>
        public event EventHandler OnLoginStart;
        /// <summary>
        /// 事件： 当用户登录成功时发生
        /// </summary>
        public event EventHandler OnLoginSucceed;
        /// <summary>
        /// 事件： 当用户登录失败时发生
        /// </summary>
        public event EventHandler OnLoginFailed;
        /// <summary>
        /// 事件：当用户注销时发生
        /// </summary>
        public event EventHandler OnLogoffStart;
        /// <summary>
        /// 事件： 当用户注销成功时发生
        /// </summary>
        public event EventHandler OnLogoffSucceed;
        /// <summary>
        /// 事件：当用户注销失败时发生
        /// </summary>
        public event EventHandler OnLogoffFailed;
        /// <summary>
        /// 事件：当用户状态改变时发生
        /// </summary>
        public event EventHandler OnStateChanged;
        /// <summary>
        /// 事件：当产生异常时发生
        /// </summary>
        public event ExceptionEventHandler OnException;
        #endregion

        #region //构造函数
        public User()
        {
            uid = 0;
            name = "";
            password = "";
            nickname = "";
            remember = false;
            autoLogin = false;
            loginCount = 0;
            lastLogDataTime = DateTime.Now;
            background = "default.jpg";
            exception = new Exception("未知");
            state = EnumState.unknown;

            if (!initLocalDataBase())
            { throw exception; }
        }
        
        public User(string UserName, string Password)
        {
            password = Password.ToMD5();
            if (Login(UserName, password)) //登录到服务器的数据
            {
                if(!readUserInfoFromLocalDatabase())
                    throw exception;
            }
            else 
                throw exception;            
        }
        #endregion

        #region //方法

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="name">用户名</param>
        /// <param name="password">密码</param>
        /// <returns>成功返回true，失败：false,填充Exception</returns>
        public bool Login(string name, string password)
        {
            bool ret = false;
            try
            {
                //触发用户登录事件
                if (OnLoginStart != null) OnLoginStart(this, new EventArgs());

                string url = String.Format("http://localhost/mysql/userlogin.php?u={0}&p={1}&f={2}", name, password, "MD5");
                if (requestService(url))
                {
                    ret = service.Read("/response", "value").ToBoolean() ? LoginfillServiceReturnSucceedData() : fillServiceReturnFailData();
                    if (!ret) throw exception;
                    else
                        if (OnLoginSucceed != null) OnLoginSucceed(this, new EventArgs());
                }
                else
                {
                    throw exception;
                }
            }
            catch (Exception ex)
            {
                ret = false;
                Exception = new Exception("用户登录异常", ex);
                if (OnLoginFailed != null) OnLoginFailed(this, new EventArgs());
            }
            return ret;
        }

        public bool Logoff(int uid)
        {
            bool ret = false;
            try
            {
                if (OnLogoffStart!=null) OnLogoffStart(this, new EventArgs());
                string url = string.Format("http://localhost/mysql/userlogin.php?uid={0}", uid);
                if (requestService(url))
                { 
                    
                    //xmlvalue("/response@value").ToBoolean()
                }
                //service.Load(string.Format("http://localhost/mysql/userlogin.php?uid={0}", uid));
                if (OnLogoffSucceed != null) OnLogoffSucceed(this, new EventArgs());
                ret = true;
            }
            catch (Exception ex)
            {
                ret = false;
                Exception = new Exception("用户注销异常", ex);
                if (OnLogoffFailed != null) OnLogoffFailed(this, new EventArgs());
            }
            return ret;
        }

        /// <summary>
        /// 用户登录时填充服务器数据返回的成功数据到User对象
        /// </summary>
        /// <returns>成功：true,失败：false,设置exception为当前异常</returns>
        private bool LoginfillServiceReturnSucceedData()
        {
            bool ret = false;
            try
            {
                name = service.Read("/response/userinfo/username", "name");
                nickname = service.Read("/response/userinfo/username", "nickname");
                uid = service.Read("/response/userinfo/username", "uid").ToInt();
                loginCount = service.Read("/response/userinfo/login", "count").ToInt();
                lastLogDataTime = service.Read("/response/userinfo/login", "lastDateTime").ToDateTime();
                state = ConvertStringToState(service.Read("/response/userinfo/login", "state"));
                ret = true;
            }
            catch (Exception ex)
            {
                Exception = new Exception("从服务器获取数据异常", ex);
                ret = false;
            }
            return ret;
        }
        /// <summary>
        /// 填充服务器数据返回的失败数据到User对象
        /// </summary>
        private bool fillServiceReturnFailData()
        {
            bool ret = false;
            try 
            {
                string number = service.Read("/response/exception", "number");
                string message = service.Read("/response/exception","");
                exception = new Exception(number+message);
            }
            catch (Exception ex) 
            {
                Exception = new Exception("", ex);
            }
            return ret;
        }


        #endregion

        
        /// <summary>
        /// 连接服务器请求xml数据。
        /// </summary>
        /// <param name="url">服务器url地址</param>
        /// <returns>成功：true，设置nav为新的数据，失败：false,设置exception</returns>
        private bool requestService(string url)
        {
            bool ret = false;
            try
            {
                service.Load(url);
                ret = true;
            }
            catch (Exception ex)
            {
                Exception = new Exception("连接服务器异常", ex);
                ret = false;
            }
            return ret;
        }

        #region //处理本地数据

        /// <summary>
        /// 初始本地数据库
        /// </summary>
        /// <returns>成功：true失败:false，填充Exception</returns>
        private bool initLocalDataBase()
        {
            bool ret = false;
            try
            {
                string db = System.AppDomain.CurrentDomain.BaseDirectory + "\\user.db";
                if (File.Exists(db))
                {
                    DB = new SQLite(db, "");
                    ret = true;
                }
                else
                {
                    throw new Exception("本地文件缺失");
                }
            }
            catch (Exception ex)
            {
                Exception = new System.Exception("初始化异常", ex);
                ret = false;
            }
            return ret;
        }

        /// <summary>
        /// 保存用户信息到本地数据库
        /// </summary>
        /// <returns>成功：true失败:false，填充Exception</returns>
        private bool saveUserInfoToLocalDatabase()
        {
            bool ret = false;
            try 
            {
                string sql = String.Format("select * from userinfo where uid={0}", uid);
                DataTable dt;
                if (DB.Select(sql, out dt))
                {
                    string pwd = remember ? password : "";

                    if (dt != null && dt.Rows.Count * dt.Columns.Count > 0)
                    {                        
                        
                        sql = String.Format("update userinfo set uname='{0}', pwd='{1}', remember={2}, autologin={3}, background='{4}'",
                            name, pwd, remember.ToShort(), autoLogin.ToShort(),background);
                        int tmp = DB.Update(sql);
                        if (tmp < 1) throw DB.Exception;
                        else ret = true;
                    }
                    else
                    {
                        sql = String.Format("insert userinfo(uid,uname,pwd,remember,autologin) values({0},'{1}','{2}',{3},{4})",
                                    uid, name, pwd, remember.ToShort(), autoLogin.ToShort(),background);
                        int tmp = DB.Insert(sql);
                        if (tmp < 1) throw DB.Exception;
                        else ret = true;
                    }
                }
                else throw DB.Exception;
            }
            catch (Exception ex)
            {
                Exception = new Exception("保存用户数据异常", ex);
                ret = false;
            }
            return ret;
        }
        /// <summary>
        /// 从本地数据库读取用户信息
        /// </summary>
        /// <returns>成功：true失败:false，填充Exception</returns>
        private bool readUserInfoFromLocalDatabase()
        {
            bool ret = false;
            try
            {
                string sql = String.Format("select * from userinfo where uid={0}", uid);
                DataTable dt;
                if (DB.Select(sql, out dt))
                {
                    if (dt != null && dt.Rows.Count * dt.Columns.Count > 0)
                    {
                        name = dt.Rows[0]["uname"].ToString();
                        password = dt.Rows[0]["pwd"].ToString();
                        autoLogin = dt.Rows[0]["autologin"].ToBoolean();
                        remember = dt.Rows[0]["remember"].ToBoolean();
                        background = dt.Rows[0]["background"].ToString();
                        ret = true;
                    }
                    else
                        throw new Exception(String.Format("不存在用户{0}",uid));
                }
                else
                    throw DB.Exception;
            }
            catch (Exception ex)
            {
                Exception = new Exception("读取用户数据异常", ex);
                ret = false;
            }
            return ret;
        }


        #endregion

        /// <summary>
        /// 用户状态枚举
        /// </summary>
        public enum EnumState
        {
            /// <summary>
            /// 未知
            /// </summary>
            unknown= 0,
            /// <summary>
            /// 离线
            /// </summary>
            offline=1,
            /// <summary>
            /// 在线
            /// </summary>
            online=2,
            /// <summary>
            /// 隐身
            /// </summary>
            hiding=3            
        }
        /// <summary>
        /// 将用户状态转换成字符串
        /// </summary>
        /// <param name="state">状态值</param>
        /// <param name="language">语言</param>
        public string ConvertStateToString(EnumState state,Language language)
        {
            switch (language)
            {
                case Language.zh_cn:
                    switch (state)
                    {
                        case EnumState.offline:
                            return "离线";
                        case EnumState.online:
                            return "在线";
                        case EnumState.hiding:
                            return "隐身";
                        default:
                            return "未知";
                    }
                default:
                    switch (state)
                    {
                        case EnumState.offline:
                            return "offline";
                        case EnumState.online:
                            return "online";
                        case EnumState.hiding:
                            return "hiding";
                        default:
                            return "unknown";
                    }
            }
          
            
        }
        /// <summary>
        /// 将用户状态转换成字符串（英文）
        /// </summary>
        /// <param name="state">状态值</param>
        public string ConvertStateToString(EnumState state)
        {
            return ConvertStateToString(state, Language.en);
        }
        public EnumState ConvertStringToState(string stateString)
        {
            switch (stateString)
            { 
                case "离线":
                case "offline":
                    return EnumState.offline;
                case "在线":
                case "online":
                    return EnumState.online;
                case "隐身":
                case "hiding":
                    return EnumState.hiding;
                default:
                    return EnumState.unknown;
            }
        }
    }
}
